home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / lib / c / val.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-04  |  6.5 KB  |  335 lines

  1. /* Three functions which extract a numeric value from a string.
  2. ** Copyright (C) 1998 David Benn
  3. ** 
  4. ** This program is free software; you can redistribute it and/or
  5. ** modify it under the terms of the GNU General Public License
  6. ** as published by the Free Software Foundation; either version 2
  7. ** of the License, or (at your option) any later version.
  8. **
  9. ** This program is distributed in the hope that it will be useful,
  10. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. ** GNU General Public License for more details.
  13. **
  14. ** You should have received a copy of the GNU General Public License
  15. ** along with this program; if not, write to the Free Software
  16. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.    
  18.    -- float val(char *) --
  19.  
  20.    Converts a string into a floating point value. 
  21.  
  22.    The string must contain a number of the following format:
  23.  
  24.     [+|-][.]nnn[.nnn][e|E[+|-]nnn]
  25.  
  26.     eg:     1234
  27.         12.25
  28.         -.12
  29.         1.5e+10    
  30.  
  31.    In other words, any legal AmigaBASIC integer or single-precision literal.
  32.  
  33.    Moreover, if the number is preceded by &H or &O the digits which follow
  34.    will be treated as hexadecimal and octal respectively.
  35.  
  36.  
  37.    -- long long_from_string(char *) --
  38.  
  39.               and
  40.  
  41.    -- short short_from_string(char *) --
  42.  
  43.    Both functions convert a string into an integer value. The first
  44.    returns a long integer, the second returns a short integer.
  45.  
  46.    The string must contain a number of the following format:
  47.  
  48.     [+|-]nnn
  49.  
  50.    -------------------------------
  51.    Author: David J Benn
  52.      Date: 19th,24th January 1993,
  53.        14th,16th February 1993,
  54.        23rd January 1994,
  55.        5th June 1994
  56.    -------------------------------
  57. */
  58.  
  59. #define BOOL     short
  60. #define BYTE     char
  61.  
  62. #define TRUE     (1L)
  63. #define FALSE     (0L)
  64. #define EOS    '\0'
  65.  
  66. #define DEC    (0L)
  67. #define OCT    (1L)
  68. #define HEX    (2L)
  69.  
  70. /* global variables */
  71. char     ch;    
  72. long    cc;
  73.  
  74. /* FFP math library bases */
  75. extern    long     MathBase;
  76. extern    long     MathTransBase;
  77.  
  78. /* FFP math functions */
  79. float    SPFlt();
  80. float    SPAdd();
  81. float    SPDiv();
  82. float    SPMul();
  83. float    SPPow();
  84.  
  85. /* functions */
  86. void nextch(str)
  87. char *str;
  88. {
  89.  /* retrieve next character from string
  90.     and convert to uppercase if necessary. 
  91.  */
  92.  ch = str[cc++];
  93.  if (ch >= 'a' && ch <= 'z') ch -= 32;
  94. }
  95.  
  96. BOOL digit(radix)
  97. long radix;
  98. {
  99. BOOL legal_digit=FALSE;
  100.  
  101.  /* test the legality of a digit */
  102.  
  103.  switch(radix)
  104.  {
  105.   case DEC : if (ch >= '0' && ch <= '9') legal_digit=TRUE; break;
  106.  
  107.   case OCT : if (ch >= '0' && ch <= '7') legal_digit=TRUE; break;
  108.  
  109.   case HEX : if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F'))
  110.         legal_digit=TRUE; break;
  111.  }
  112.  
  113.  return(legal_digit);
  114. }
  115.  
  116. long digit_value(radix)
  117. long radix;
  118. {
  119. long value=0;
  120.  
  121.  /* return the actual value of a digit (legality assumed) */
  122.  
  123.  switch(radix)
  124.  {
  125.   case DEC :    
  126.   case OCT :    value = ch-'0';        
  127.         break;  
  128.  
  129.   case HEX :      if (ch <= '9') value = ch-'0'; else value = 10+ch-'A';
  130.         break;
  131.  }
  132.  
  133.  return(value);
  134. }
  135.  
  136. float val(str)
  137. char *str;
  138. {
  139. long    radix;
  140. long     base;
  141. long     i;
  142. long     n[2];
  143. long     index;
  144. long     periods;
  145. long    placecount;
  146. long     places;
  147. long    ex;
  148. long     ex_sign;
  149. BOOL    period;
  150. float     sign;
  151. float    singleval;
  152.  
  153.   /* start of string */
  154.   cc=0;
  155.  
  156.   /* assume base 10 */
  157.   radix=DEC;
  158.   base=10;
  159.  
  160.   /* convert str to float */
  161.   nextch(str);
  162.   while (ch <= ' ' && ch != EOS) nextch(str);  /* skip leading whitespace */
  163.  
  164.   /* &H or &O? */
  165.   if (ch == '&')
  166.   {
  167.    nextch(str);
  168.    switch(ch)
  169.    {
  170.     case 'H' : radix=HEX; base=16; break;
  171.     case 'O' : radix=OCT; base=8;  break;
  172.     default  : return(0.0);    /* unknown symbol */
  173.    }
  174.    nextch(str);
  175.   }
  176.    
  177.   /* + | - */
  178.   switch(ch)
  179.   {
  180.    case '-' :     sign = -1.0; nextch(str); 
  181.         break;
  182.   
  183.    case '+' :    sign = 1.0; nextch(str);
  184.         break;
  185.  
  186.    default  :    sign = 1.0; 
  187.   }
  188.  
  189.   if (digit(radix) || (ch == '.'))
  190.   {
  191.    n[0]=n[1]=0;
  192.    index=0;
  193.    period=FALSE;
  194.    periods=0;
  195.    placecount=0;
  196.    
  197.    /* is first char '.'? */
  198.    if (ch == '.')
  199.    {
  200.     period=TRUE;
  201.     placecount=0;
  202.     index=1;
  203.     periods++;
  204.    }
  205.    /* get the value */
  206.    if (!period) n[0]=base*n[0]+digit_value(radix);
  207.    do
  208.    {
  209.     nextch(str);
  210.     if (digit(radix)) n[index]=base*n[index]+digit_value(radix);
  211.     if (digit(radix) && period) placecount++;
  212.     if (ch == '.') periods++;
  213.     if ((ch == '.') && (!period))
  214.     {
  215.      period=TRUE;
  216.      placecount=0;
  217.      index=1;
  218.     }
  219.    }
  220.    while ((digit(radix) || ch == '.') && (periods <= 1));
  221.  
  222.    /* integer or real? */
  223.    if (period && (periods == 1) && radix == DEC)
  224.    {
  225.     /* make FFP */
  226.     places=1;
  227.     for (i=1;i<=placecount;i++) places *= base;
  228.     singleval = SPAdd(SPFlt(n[0]),SPDiv(SPFlt(places),SPFlt(n[1])));
  229.    }  
  230.    else 
  231.        singleval = SPFlt(n[0]);
  232.  
  233.    if (radix != DEC) return(singleval);
  234.  
  235.    /* is it a real in exponential form? */
  236.    if (ch == 'E')
  237.    {
  238.     ex=0;
  239.     ex_sign=1;
  240.     nextch(str);
  241.     if (ch == '+') { ex_sign=1; nextch(str); }
  242.     else
  243.        if (ch == '-') { ex_sign=-1; nextch(str); }
  244.     if (!digit(radix)) singleval = 0.0;  /* expected a digit so just return 0 */ 
  245.     /* get digits */
  246.     while (digit(radix)) { ex = base*ex+digit_value(radix); nextch(str); }
  247.     ex *= ex_sign;
  248.  
  249.     /* convert to FFP */
  250.     if ((ex >= -20) && (ex <= 18))
  251.     {
  252.      /* if exponent is zero then singleval=singleval*1 since 10^0 = 1 */
  253.      if (ex != 0) 
  254.          singleval=SPMul(SPPow(SPFlt(ex),10.0),singleval); /* n * 10^ex */
  255.     }
  256.     else 
  257.         singleval=0.0;     /* exponent out of range, so just return 0 */ 
  258.    }
  259.   }
  260.   else 
  261.       singleval=0.0;   /* illegal character for start of number */   
  262.  
  263.   singleval = SPMul(singleval,sign);    /* positive or negative */
  264.  
  265.  return(singleval);
  266.  
  267. long long_from_string(str)
  268. char *str;
  269. {
  270. long    radix;
  271. long     base;
  272. long    sign;
  273. long    longval;
  274.  
  275.   /* set final value to zero */
  276.   longval=0;
  277.  
  278.   /* start of string */
  279.   cc=0;
  280.  
  281.   /* assume base 10 */
  282.   radix=DEC;
  283.   base=10;
  284.  
  285.   /* convert str to long integer */
  286.   nextch(str);
  287.   while (ch <= ' ' && ch != EOS) nextch(str);  /* skip leading whitespace */
  288.  
  289.   /* &H or &O? */
  290.   if (ch == '&')
  291.   {
  292.    nextch(str);
  293.    switch(ch)
  294.    {
  295.     case 'H' : radix=HEX; base=16; break;
  296.     case 'O' : radix=OCT; base=8;  break;
  297.     default  : return(0);    /* unknown symbol */
  298.    }
  299.    nextch(str);
  300.   }
  301.    
  302.   /* + | - */
  303.   switch(ch)
  304.   {
  305.    case '-' :     sign = -1; nextch(str); 
  306.         break;
  307.   
  308.    case '+' :    sign = 1; nextch(str);
  309.         break;
  310.  
  311.    default  :    sign = 1; 
  312.   }
  313.  
  314.   /* extract the integer value */
  315.   longval=0;
  316.  
  317.   /* get the value */
  318.   while (digit(radix))
  319.   {
  320.    longval=base*longval+digit_value(radix);
  321.    nextch(str);
  322.   }
  323.  
  324.  longval *= sign;
  325.  
  326.  return(longval);
  327. }
  328.  
  329. short short_from_string(str)
  330. char *str;
  331. {
  332.  return((short)long_from_string(str));
  333. }
  334.